from typing import Optional, Dict, Any, List
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func, or_, and_
from fastapi import HTTPException, status
from modules.system.models.dept import Department
from modules.system.schemas.dept_schemas import DeptCreate, DeptUpdate
from modules.system.params.dept_params import DeptQuery
from modules.system.curd.dept_curd import dept_dao
from core.permission.decorators import with_permission
from sqlalchemy import text
from core.base.base_service import BaseService
from core.pagination import paging_data, _CustomPageParams
from utils.build_tree import get_tree_data
from utils.query_builder import build_select_stmt

class DeptService(BaseService):
    """部门管理服务"""

    @staticmethod
    async def get_dept_by_id(db: AsyncSession, dept_id: int) -> Optional[Department]:
        return await dept_dao.get_by_id(db, dept_id)

    @staticmethod
    async def get_dept_by_code(db: AsyncSession, dept_code: str) -> Optional[Department]:
        return await dept_dao.get_by_code(db, dept_code)

    @staticmethod
    async def get_dept_by_name(db: AsyncSession, dept_name: str) -> Optional[Department]:
        return await dept_dao.get_by_name(db, dept_name)

    @staticmethod
    @with_permission(Department.__tablename__)
    async def get_depts_with_pagination(
        db: AsyncSession,
        query_params: DeptQuery,
        permission_condition: Optional[str] = None
    ) -> Dict[str, Any]:
        stmt = build_select_stmt(
            Department,
            query_params,
            text_like_fields={"dept_name", "dept_code"},
        )
        # 与部门列表保持一致，按 dept_code 升序
        stmt = stmt.order_by(Department.dept_code.asc())
        if permission_condition and permission_condition != "1=1":
            stmt = stmt.where(text(permission_condition))
        params = _CustomPageParams(page=query_params.page, size=query_params.size)
        return await paging_data(db, stmt, params=params)

    @staticmethod
    async def create_dept(db: AsyncSession, payload: DeptCreate) -> Department:
        if await DeptService.get_dept_by_code(db, payload.dept_code):
            raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="事业部编码已存在")
        if await DeptService.get_dept_by_name(db, payload.dept_name):
            raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="事业部名称已存在")
        dept = await dept_dao.create(db, payload)
        await db.commit()
        await db.refresh(dept)
        return dept

    @staticmethod
    async def update_dept(db: AsyncSession, dept_id: int, payload: DeptUpdate) -> Department:
        dept = await dept_dao.update(db, dept_id, payload)
        if not dept:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="事业部不存在")
        await db.commit()
        await db.refresh(dept)
        return dept

    @staticmethod
    async def delete_dept(db: AsyncSession, dept_id: int) -> None:
        ok = await dept_dao.delete(db, dept_id)
        if not ok:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="事业部不存在")
        await db.commit()
        return None

    @staticmethod
    async def get_dept_tree(db: AsyncSession, status: Optional[bool] = None) -> List[Dict[str, Any]]:
        rows = await dept_dao.select_by_query(db, DeptQuery(status=status))
        return get_tree_data(rows, is_sort=True, sort_key='dept_code')

    @staticmethod
    async def get_dept_children_codes(db: AsyncSession, dept_code: str) -> List[str]:
        """获取指定部门及其所有子部门的编码列表"""
        if not dept_code:
            return []
        
        # 直接从数据库查询所有部门，基于parent_code关系构建层级
        result = await db.execute(select(Department))
        all_depts = result.scalars().all()
        # 构建部门映射
        dept_map = {dept.dept_code: dept for dept in all_depts if dept.dept_code}
        
        # 检查目标部门是否存在
        if dept_code not in dept_map:
            return []
                  
        # 递归查找所有子部门
        def find_children_recursive(parent_code: str) -> List[str]:
            children_codes = []
            for dept in all_depts:
                if dept.parent_code == parent_code and dept.dept_code != parent_code:
                    children_codes.append(dept.dept_code)
                    # 递归查找这个子部门的子部门
                    grandchildren = find_children_recursive(dept.dept_code)
                    children_codes.extend(grandchildren)
            
            return children_codes
        
        # 获取目标部门及其所有子部门的编码
        result_codes = [dept_code]  # 包含目标部门自己
        children_codes = find_children_recursive(dept_code)
        result_codes.extend(children_codes)
        return result_codes